package org.zjt.invoke;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.invoke.*;

/**
 * Description:
 *
 *      1、invoke 刚开始会利用本地方法反射执行。在多次执行后，生成代理并不会调用本地方法反射。
 *
 *      2、invokedynamic 会得到方法的引用，利用命令行操作，性能更好。
 *
 * @author juntao.zhang
 * Date: 2018-11-06 22:19
 * @see
 */
public class InvokeMethod {




    /**
     * jdk的反射
     * @param args
     * @throws Throwable
     *
     * 6246 ms
     */
    public static void invoke()throws Throwable {
        Method method = InvokeMethod.class.getDeclaredMethod("method1");

        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000_000; i++) {
            Object invoke = method.invoke(InvokeMethod.class, new String[]{});
        }
        long time1 = System.currentTimeMillis() - start;

        System.out.println("time:" + String.valueOf(System.currentTimeMillis() - start));
    }


    /**
     * jdk 新的反射执行器（since 7） invokedynamic
     * @throws Throwable
     *
     * 6295 ms
     */
    public static void newInvokder() throws Throwable{
        // invokedynamic 的实现
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        //方法参数类型。
        MethodType t = MethodType.methodType(void.class,Object.class,Object.class);

        //方法签名
        MethodHandle mh = lookup.findStatic(InvokeMethod.class, "bar", t);


        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000_000; i++) {
            //得到方法的引用，不用每次检查方法是否可执行
            mh.invokeExact(new Object(),new Object());
        }
        System.out.println("time:" + String.valueOf(System.currentTimeMillis() - start));
    }


    private static void bar(Object o,Object o1) {
        System.out.println("----------bar----------");
//        new RuntimeException().printStackTrace();
    }



    public static void method1() {
        System.out.println("----------xxxxx----------");
//        new RuntimeException().printStackTrace();
    }
}





